package cn.sourcespro.shiro.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * security
 *
 * @author zhanghaowei
 * @date 2018/7/20
 */
public class JwtTokenUtil {

    private static final Logger logger = LoggerFactory.getLogger(JwtTokenUtil.class);

    /**
     * token秘钥，请勿泄露，请勿随便修改 backups:bB234j9H23JDFA_
     */
    private static final String SECRET = "bB234j9H23JDFA_";
    /**
     * token 过期时间: 10天
     */
    private static final int CALENDAR_FIELD = Calendar.DATE;
    private static final int CALENDAR_INTERVAL = 10;

    /**
     * 创建PC token
     *
     * @param userId 用户id
     * @return jwt
     */
    public static String createPcToken(Long userId, Set<String> roleSet, Set<String> permSet) {
        return createToken(userId, "PC", roleSet, permSet);
    }

    /**
     * 创建PC token
     *
     * @param userId 用户id
     * @return jwt
     */
    public static String createAppToken(Long userId, Set<String> roleSet, Set<String> permSet) {
        return createToken(userId, "APP", roleSet, permSet);
    }


    /**
     * 创建token
     *
     * @param userId  用户id
     * @param subject 对象 pc || app
     * @param permSet
     * @return token
     */
    public static String createToken(Long userId, String subject, Set<String> roleSet, Set<String> permSet) {
        Date iatDate = new Date();
        // expire time
        Calendar calendar = Calendar.getInstance();
        calendar.add(CALENDAR_FIELD, CALENDAR_INTERVAL);
        Date expiresDate = calendar.getTime();

        // header Map
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        // build token
        String[] roles = new String[roleSet.size()];
        roleSet.toArray(roles);
        String[] perms = new String[permSet.size()];
        permSet.toArray(perms);
        return JWT.create().withHeader(map)
                .withIssuer("server")
                .withSubject(subject)
                .withArrayClaim("roles", roles)
                .withArrayClaim("perms", perms)
                .withAudience(String.valueOf(userId))
                .withIssuedAt(iatDate)
                .withExpiresAt(expiresDate)
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 解密Token
     *
     * @param token token
     * @return DecodedJWT
     */
    public static DecodedJWT verifyToken(String token) throws JWTVerificationException {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        return verifier.verify(token);
    }

    /**
     * 根据Token获取userId
     *
     * @param token token
     * @return userId
     */
    public static Long getUid(String token) throws JWTVerificationException {
        DecodedJWT decodedJWT = verifyToken(token);
        return Long.valueOf(decodedJWT.getAudience().get(0));
    }

}
